﻿using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using SocialApi.Core.Extensions;
using SocialApi.Core.Request;
using SocialApi.Instagram.AppSettings;

namespace SocialApi.Instagram.Entities.Methods.Tags
{
    internal class TagMethods : ITagMethods
    {
        #region Члены ITagMethods

        /// <summary>
        /// Название отметки
        /// </summary>
        public string Name { get; private set; }

        #region Информация

        /// <summary>
        /// Получает информацию об <see cref="name"/> отметке
        /// </summary>
        /// <param name="name">Имя отметки</param>
        /// <returns>Информация об отметке</returns>
        public ITagMethods Get(string name)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, string.Format(ApiUrls.Tag, name));
            var jObject = JObject.Parse(Navigator.Instance.Get(url));
            InstagramService.CheckResult(jObject);
            return jObject["data"].ToObject<TagMethods>();
        }

        /// <summary>
        /// Асинхронно получает информацию об <see cref="name"/> отметке
        /// </summary>
        /// <param name="name">Имя отметки</param>
        /// <returns>Информация об отметке</returns>
        public async Task<ITagMethods> GetAsync(string name)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, string.Format(ApiUrls.Tag, name));
            var result = await Navigator.Instance.GetAsync(url);
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
            return jObject["data"].ToObject<TagMethods>();
        }

        #endregion

        #region Список медиа

        /// <summary>
        /// Получает список недавно отмеченных медиа
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <returns>Список недавно отмеченных медиа</returns>
        public IEnumerable<IResult> Recent(string name)
        {
            return Recent(name, -1, -1);
        }

        /// <summary>
        /// Получает список недавно отмеченных медиа
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <param name="minId">Возвращает медиа меньше заданого параметра</param>
        /// <param name="maxId">Возвращает медиа больше заданого параметра</param>
        /// <returns>Список недавно отмеченных медиа</returns>
        public IEnumerable<IResult> Recent(string name, int minId, int maxId)
        {
            var url = CreateRecentUrl(name, minId, maxId);
            var jObject = JObject.Parse(Navigator.Instance.Get(url));
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<Result>>();
#else
            return jObject["data"].ToObject<List<Result>>() as IEnumerable<IResult>;
#endif
        }

        /// <summary>
        /// Асинхронно получает список недавно отмеченных медиа
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <returns>Cписок недавно отмеченных медиа</returns>
        public async Task<IEnumerable<IResult>> RecentAsync(string name)
        {
            var result = await RecentAsync(name, -1, -1);
            return result;
        }

        /// <summary>
        /// Асинхронно получает список недавно отмеченных медиа
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <param name="minId">Возвращает медиа меньше заданого параметра</param>
        /// <param name="maxId">Возвращает медиа больше заданого параметра</param>
        /// <returns>Cписок недавно отмеченных медиа</returns>
        public async Task<IEnumerable<IResult>> RecentAsync(string name, int minId, int maxId)
        {
            var url = CreateRecentUrl(name, minId, maxId);
            var result = await Navigator.Instance.GetAsync(url);
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<Result>>();
#else
            return jObject["data"].ToObject<List<Result>>() as IEnumerable<IResult>;
#endif
        }

        private static string CreateRecentUrl(string name, int minId, int maxId)
        {
            var result = new StringBuilder(InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, string.Format(ApiUrls.Tag, name), "/", ApiUrls.MediaRecent));
            if (minId.Exists())
            {
                result.AppendFormat("&min_id={0}", minId);
            }
            if (maxId.Exists())
            {
                result.AppendFormat("&max_id={0}", maxId);
            }
            return result.ToString();
        }

        #endregion

        #region Поиск

        /// <summary>
        /// Поиск медия по имени
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <returns>Список медия по имени</returns>
        public IEnumerable<ITagMethods> Search(string name)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, string.Format(ApiUrls.Tag, "search"));
            var jObject = JObject.Parse(Navigator.Instance.Get(string.Format("{0}&q={1}", url, name)));
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<TagMethods>>();
#else
            return jObject["data"].ToObject<List<TagMethods>>() as IEnumerable<ITagMethods>;
#endif
        }

        /// <summary>
        /// Асинхронный поиск медия по имени
        /// </summary>
        /// <param name="name">Имя медиа</param>
        /// <returns>Список медия по имени</returns>
        public async Task<IEnumerable<ITagMethods>> SearchAsync(string name)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, string.Format(ApiUrls.Tag, "search"));
            var result = await Navigator.Instance.GetAsync(string.Format("{0}&q={1}", url, name));
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<TagMethods>>();
#else
            return jObject["data"].ToObject<List<TagMethods>>() as IEnumerable<ITagMethods>;
#endif
        }

        #endregion

        #endregion
    }
}